package logic;

/**
 * class representing game engine - it includes game model (data) and controller (handling game logic)
 * @author Rekin
 *
 */
public class Engine {
	public static final int defaultStake = 5;
	public static final int defaultEntryFee = 2;
	
	protected TempUserSettings predefinedSettings;
	protected Player players[];
	protected int cardDeck[][];
	protected int playerNumber;
	protected int playerToMove;
	protected int soundLevel;
	protected int currentStake;
	protected int currentRound;
	protected int moneyOnBoard;
	protected int roundWinner;
	protected String winnerName;
	protected boolean totalGameVictory;
	protected boolean totalGameDefeat;
	protected boolean canSave;

	/**
	 * constructor of engine with a given parameters
	 * @param temp parameters for engine
	 */
	public Engine(TempUserSettings temp){
		predefinedSettings=temp;
		playerNumber=predefinedSettings.getPlayerNumer();
		soundLevel=predefinedSettings.getSoundLevel();
		initCardDeck();
		playerToMove=0;
		currentStake=defaultStake;
		currentRound=0;
		moneyOnBoard=0;
		roundWinner=-1;
		winnerName="";
		totalGameVictory=false;
		totalGameDefeat=false;
	}
	
	/**
	 * initiates players 
	 * super class logic - should be overriden
	 */
	protected void initPlayers(){
		System.out.println("Engine - initPlayers() - should be overriden!!");
	}
	
	/**
	 * super class logic - should be overriden
	 * @param pressedButton button that was hit
	 */
	public void doLogic(int pressedButton){
		System.out.println("Engine - doLogic(int) - should be overriden!!");
	}
	
	/**
	 * initiates card deck
	 */
	protected void initCardDeck(){
		if(cardDeck==null)
			cardDeck=new int[4][13];
		
		for(int i=0;i<4;++i){
			for(int j=0;j<13;++j){
				cardDeck[i][j]=1;
			}
		}
	}
	
	/**
	 * finds player that is only one not dropped from game
	 * @return last player in game index or -1 if there are more players still in game
	 */
	protected int getOnlyOneNotDropped(){
		int droppedPlayers=0;
		for(int j=0;j<getPlayerNumber();++j){
			if(!getPlayer(j).isInGame()){
				++droppedPlayers;
			}
		}
		if(getPlayerNumber()-droppedPlayers < 2){
			for(int j=0;j<getPlayerNumber();++j){
				if(getPlayer(j).isInGame()){
					return j;
				}
			}
		}
		return -1;
	}
	
	/**
	 * @return starting money
	 */
	public int getStartingMoney(){
		return predefinedSettings.getStartingMoney();
	}
	
	/**
	 * method for taking entry fees from players at the start of each round
	 */
	protected void takeEntryFee(){
		for(int i=0; i<players.length; ++i){
			if(!players[i].isBankrupt()){
				players[i].substractMoney(defaultEntryFee);
				moneyOnBoard+=defaultEntryFee;
			}
		}
	}

	/**
	 * method for finding a game winner
	 * @return winner player index - notify that we assume that there can be no draw
	 */
	protected int whoWon(){
		//logic for finding winner
		int pwhs=0; // -> playerWithHighestSequence
		while(!players[pwhs].isInGame() || players[pwhs].isBankrupt()){
			++pwhs;
		}
		int phs=players[pwhs].getSequenceKind(); // ->highest player's sequence
		for(int i=pwhs+1;i<playerNumber;++i){
			if(players[i].isBankrupt() || !players[i].isInGame())
				continue;
			phs=players[pwhs].getSequenceKind();
			if(phs<players[i].getSequenceKind()){
				//if next one has higher sequence:
				pwhs=i;
			}
			else if(phs==players[i].getSequenceKind()){///if both have same sequences
				//if next has higher highest sequence card
				if(players[pwhs].getSequenceHighest()<players[i].getSequenceHighest()){
					pwhs=i;
				}
				//if same sequence kind cards
				else if(players[pwhs].getSequenceHighest()==players[i].getSequenceHighest()){
					//we check the colors of cards
					int hpc=players[pwhs].getHighestCardColor(); //highest player color
					int npc=players[i].getHighestCardColor(); //new player color
					
					if(hpc==3 || (hpc==1 && (npc==0 || npc==2)) || (hpc==0 && npc==2) ){
						//if new color higher than old one
						pwhs=i;
					}
				}		
			}
		}
		return pwhs;
	}
	
	
	/**
	 * @param ind index of player
	 * @return Player object
	 */
	public Player getPlayer(int ind){
		return players[ind];
	}

	/**
	 * @return playerNumber
	 */
	public int getPlayerNumber() {
		return playerNumber;
	}

	/**
	 * @param playerNumber
	 */
	public void setPlayerNumber(int playerNumber) {
		this.playerNumber = playerNumber;
	}

	/**
	 * @return playerToMove
	 */
	public int getPlayerToMove() {
		return playerToMove;
	}

	/**
	 * @param playerToMove
	 */
	public void setPlayerToMove(int playerToMove) {
		this.playerToMove = playerToMove;
	}

	/**
	 * @return currentStake
	 */
	public int getCurrentStake() {
		return currentStake;
	}

	/**
	 * @param currentStake
	 */
	public void setCurrentStake(int currentStake) {
		this.currentStake = currentStake;
	}

	/**
	 * @return currentRound
	 */
	public int getCurrentRound() {
		return currentRound;
	}

	/**
	 * @param currentRound
	 */
	public void setCurrentRound(int currentRound) {
		this.currentRound = currentRound;
	}
	
	/**
	 * increments current sub-round
	 */
	public void incRound(){
		++currentRound;
	}

	/**
	 * @return moneyOnBoard
	 */
	public int getMoneyOnBoard() {
		return moneyOnBoard;
	}

	/**
	 * @param moneyOnBoard
	 */
	public void setMoneyOnBoard(int moneyOnBoard) {
		this.moneyOnBoard = moneyOnBoard;
	}

	/**
	 * @return cardDeck as int[][]
	 */
	public int[][] getCardDeck() {
		return cardDeck;
	}

	/**
	 * @param cardDeck
	 */
	public void setCardDeck(int[][] cardDeck) {
		this.cardDeck = cardDeck;
	}

	/**
	 * @return winnerName
	 */
	public String getWinnerName() {
		return winnerName;
	}

	/**
	 * @return totalGameVictory
	 */
	public boolean isTotalGameVictory() {
		return totalGameVictory;
	}

	/**
	 * @return totalGameDefeat
	 */
	public boolean isTotalGameDefeat() {
		return totalGameDefeat;
	}
	
	/**
	 * @return flag indicating that game can be saved (true when sub-round and player to move is correct)
	 */
	public boolean isCanSave() {
		return canSave;
	}

	/**
	 * @return round winner
	 */
	public int getRoundWinner() {
		return roundWinner;
	}

	/**
	 * @param roundWinner
	 */
	public void setRoundWinner(int roundWinner) {
		this.roundWinner = roundWinner;
	}

	/**
	 * @param winnerName
	 */
	public void setWinnerName(String winnerName) {
		this.winnerName = winnerName;
	}
}
